<template>
  <view class="sku-cc">
    <slot name="sku" v-for="(specMap, row) in mSpecList" :row="row" :specMap="specMap" :disable="disable" :active="specMap.active"></slot>
  </view>
</template>

<script>
/**
 * sku主组建
 */
export default {
  title: "sku-cc",
  props: {
    /**
     * 属性Map列表
     */
    specList: {
      type: Array,
      default: []
    },
    /**
     * sku列表
     */
    skuList: {
      type: Array,
      default: []
    },
    /**
     * 是否禁止选择
     */
    disable: {
      type: Boolean,
      default: false
    },
    /**
     * 默认选中
     */
    selectedIndex: {
      type: Number,
      default: -1
    },
    /**
     * 属性项列表的key
     */
    specListKey: {
      type: String,
      default: 'specList'
    },
    /**
     * sku的属性Id集的key
     */
    specIdsKey: {
      type: String,
      default: 'specIds'
    },
    /**
     * sku属性集的分隔符
     */
    separator: {
      type: String,
      default: ','
    },
    /**
     * 单个属性项的正则匹配值，也是默认的代替值。这里使用specId来验证，不同的规则可以自己定义，可以为中文等等。
     */
    specPattern: {
      type: String,
      default: '[0-9]*'
    },
  },
  computed: {
    /**
     * 是否需要做sku可选判断,如果sku数量全满,则没必要做判断
     * @returns {boolean}
     */
    skuCheckStatus() {
      return (this.specList.length <= 0 ? 0 : this.specList.map(item => item[this.specListKey].length ?? 0).reduce((a, b) => a * b)) === (this.skuList.length ?? 0);
    },
    /**
     * 已选中的序号列表
     * @returns {(number|boolean|default.watch.active|boolean|ServiceWorker|*)[]}
     */
    selectedSpecIndexList() {
      return this.mSpecList.map(item => item.active);
    },
  },
  data() {
    return {
      mSpecList: [],
      mSelectedIndex: -1
    };
  },
  watch: {
    specList(newValue) {
      this.init(newValue);
    },
    selectedSpecIndexList(newValue) {
      this.updateSpecListDisable();

      let specAllSelected = this.selectedSpecIndexList.every(active => active > -1);

      if (specAllSelected) {
        this.selectedSku();
        this.$emit('selectedSkuObj', this.skuList[this.mSelectedIndex]);
      } else {
        this.mSelectedIndex = -1;
      }

      this.$emit('getSelectedIndex', this.mSelectedIndex);
      this.$emit('getSelectedSkuObj', this.skuList[this.mSelectedIndex] ?? null);
    }
  },
  mounted() {
    this.init(this.specList);
    this.selectedSku(this.selectedIndex);
    uni.$on("updateSkuSpecItemActive", e => this.updateItemActive(e));
  },
  beforeDestroy() {
    // 清除监听
    uni.$off('updateSkuSpecItemActive');
  },
  methods: {
    /**
     * 初始化 active状态 disable状态
     * @param specList
     */
    init(specList) {
      let updateSpecList = JSON.parse(JSON.stringify(specList));

      for (let spec of updateSpecList) {
        //添加active状态
        spec.active = -1;
        for (let specItem of spec[this.specListKey]) {
          //添加disable状态
          spec.disable = false;
        }
      }

      this.mSpecList = updateSpecList;
    },
    /**
     * 获取单个选中属性值对应的sku属性id集合
     * @param selectedSpecIndexList
     * @returns {*}
     */
    getSelectedSpecIds(selectedSpecIndexList) {
      return selectedSpecIndexList.map((active, row) => active > -1 ? this.mSpecList[row][this.specListKey][active].id : this.specPattern).join(this.separator)
    },
    /**
     * 检测一个规格属性值是否禁止
     * @param row
     * @param active
     * @returns {boolean}
     */
    checkSpecItemDisable(row, active) {
      if (this.skuCheckStatus) {
        return false;
      }

      let selectedSpecIndexList = JSON.parse(JSON.stringify(this.selectedSpecIndexList));

      selectedSpecIndexList[row] = active;

      let skuPattern = this.getSelectedSpecIds(selectedSpecIndexList),
          skuReg = new RegExp(skuPattern),
          able = this.skuList.some(item => skuReg.test(item[this.specIdsKey]));

      return !able;
    },
    /**
     * 更新规格禁止状态
     */
    updateSpecListDisable() {
      let that = this, index;
      this.mSpecList.map((specMap, row) => {
        for (index in specMap[that.specListKey]) {
          this.$set(specMap[that.specListKey][index], 'disable', that.checkSpecItemDisable(row, index));//优化点击事件不更新
        }
      })
    },
    /**
     * 选中一个sku
     * @param skuIndex
     */
    selectedSku(skuIndex = -1) {
      if (this.skuList.length > 0) {
        if (skuIndex > -1 && skuIndex < this.skuList.length) {
          //主动选择
          if (this.skuList.length > skuIndex) {
            let specIds = this.skuList[skuIndex][this.specIdsKey];
            specIds.split(this.separator).map((specId, row) => {
              for (let index in this.mSpecList[row][this.specListKey]) {
                if (this.mSpecList[row][this.specListKey][index].id == specId) {
                  this.$set(this.mSpecList, 'active', index);//优化点击事件不更新
                  break;
                }
              }
            })
          }
        } else {
          //被动选择
          let specIds = this.getSelectedSpecIds(this.selectedSpecIndexList);
          for (let index in this.skuList) {
            if (specIds == this.skuList[index][this.specIdsKey]) {
              this.mSelectedIndex = index;
              break;
            }
          }
        }
      }
    },
    /**
     * 事件回调
     * @param e
     */
    updateItemActive(e) {
      if (!this.disable) {
        let row = e.row ?? 0;
        this.$set(this.mSpecList[row], 'active', e.index ?? -1);//优化点击事件不更新
      }
    },
    /**
     * 获取当前选中sku序号,未选中为-1
     * @returns {number}
     */
    getSelectedIndex() {
      return this.mSelectedIndex;
    },
    /**
     * 获取当前选中sku对象,未选中为null
     * @returns {*|null}
     */
    getSelectedSkuObj() {
      return this.skuList[this.mSelectedIndex] ?? null;
    }
  }
}
</script>

<style lang="scss">
.sku-cc {

}
</style>
